import cgi
import wsgiref.handlers
import os
import logging
import xmlrpclib

os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
from google.appengine.dist import use_library
use_library('django', '1.2')

from google.appengine.ext.webapp import template
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
from google.appengine.api import memcache


class Content(db.Model):
  content = db.StringProperty(multiline=True)
  date = db.DateTimeProperty(auto_now_add=True)

class Downloads(db.Model):
  count = db.IntegerProperty()
  description = db.StringProperty()
  filename = db.StringProperty()
  date = db.DateTimeProperty(auto_now_add=True)
  recommend = db.StringProperty()
  order = db.IntegerProperty()
  blobkey = db.StringProperty()
  size = db.IntegerProperty()

class Pingbacks(db.Model):
  localurl = db.StringProperty()
  remoteurl = db.StringProperty()
  date = db.DateTimeProperty(auto_now_add=True)
  valid = db.BooleanProperty()


class Newsfeed(webapp.RequestHandler):
  def get(self):
    self.response.headers['Content-Type'] = 'application/rss+xml'
    self.response.headers['charset'] = 'utf-8'

    content = memcache.get("contlastten")
    if content == None:
      content = Content.all().order('-date').fetch(10)
      memcache.add("contlastten", content, 3600)

    template_values = {
      'content': content,
      }

    path = os.path.join(os.path.dirname(__file__), 'newsfeed.rss')
    self.response.out.write(template.render(path, template_values))


class Count(webapp.RequestHandler):
  def get(self):
    self.response.out.write('<html>\n<head><title>GRaiN Download Count</title></head>\n<body>\n<table border="1">\n')
    self.response.out.write('<thead><th>filename</th><th>downloads</th><th>date</th><th>recommend</th><th>order</th></thead>\n<tbody align=center>')
    #downloads = db.GqlQuery("SELECT * FROM Downloads WHERE order > 0 ORDER BY order DESC")
    downloads_query = Downloads.all().order('-order')
    downloads = downloads_query.fetch(50)

    for download in downloads:
      self.response.out.write('<tr><td>')
      self.response.out.write('\nfile: '+ download.filename)
      self.response.out.write('</td><td>')
      self.response.out.write(download.count)
      self.response.out.write('</td><td>')
      self.response.out.write(download.date)
      self.response.out.write('</td><td>')
      self.response.out.write(download.recommend)
      self.response.out.write('</td><td>')
      self.response.out.write(download.order)
      self.response.out.write('</td></tr>\n')

    self.response.out.write('</tbody></table></body></html>')


class Notifier(webapp.RequestHandler):
  def get(self):
    content = memcache.get("contlastten")
    if content == None:
      content = Content.all().order('-date').fetch(10)
      memcache.add("contlastten", content, 3600)
    files = memcache.get("filebyorder")
    if files == None:
      files = Downloads.all().filter("order >",0).order('-order').fetch(20)
      memcache.add("filebyorder", files, 3600)

    self.response.headers['X-UA-Compatible'] = 'IE=9'
    self.response.headers['X-Pingback'] = 'http://yoni-zaf.appspot.com/pingback'
 
    template_values = {
      'content': content,
      'files': files,
      'homepage': self.request.path,
      'path': 'home',
      }
    path = os.path.join(os.path.dirname(__file__), 'enotifier.html')
    self.response.out.write(template.render(path, template_values))
  def head(self):
    self.response.headers['X-Pingback'] = 'http://yoni-zaf.appspot.com/pingback'
    logging.debug ('got HEAD request')



class Files(blobstore_handlers.BlobstoreDownloadHandler):
  def get(self):
    def increment_counter(key, amount):
      obj = db.get(key)
      obj.count += amount
      obj.put()
    downloads = db.GqlQuery("SELECT * FROM Downloads WHERE filename = '"+self.request.path+"' LIMIT 1")
    dowkey = downloads.get()
    order=0
    blobkey=""
    for download in downloads:
      order = download.order
      blobkey = download.blobkey

    if order>0:
      db.run_in_transaction(increment_counter, dowkey.key(), 1)

    logging.info ('download: %s.', self.request.path)
    if blobkey == "" or blobkey == None:
      if os.path.isfile('./static'+self.request.path):
        self.response.headers['Content-Type'] = 'application/zip'
        fileh = open('./static'+self.request.path,'rb')
        self.response.out.write(fileh.read())
      else:
        senderror(self)
    else:
      blob_info = blobstore.BlobInfo.get(blobkey)
      self.send_blob(blob_info)



class Upload(blobstore_handlers.BlobstoreUploadHandler):
  def post(self):
    upload_files = self.get_uploads('file')
    for file in upload_files:
      d = Downloads(
                   count = 0,
                   description = self.request.get("desc"),
                   filename = '/files/%s' % file.filename,
                   order = int(self.request.get("order")),
                   blobkey = str(file.key()),
                   size = file.size,
                   recommend = self.request.get("recommend")
                   )
      d.put()
    if int(self.request.get("order")) > 0:
      memcache.flush_all()
    self.redirect('/')


class PostNewsEntry(webapp.RequestHandler):
  def post(self):
    pne = Content(content = self.request.get("newspost"))
    pne.put()
    memcache.flush_all()
    self.redirect('/')


class Html(webapp.RequestHandler):
  def get(self):
    self.response.headers['Content-Type'] = 'text/html'
    self.response.headers['X-UA-Compatible'] = 'IE=9'
    self.response.headers['X-Pingback'] = 'http://yoni-zaf.appspot.com/pingback'
    if os.path.isfile("."+self.request.path):
      template_values = {
        'path': "."+self.request.path,
        'url': self.request.url,
        }
      if self.request.path == "/admin/upload.html":
        template_values['upload_url'] = blobstore.create_upload_url('/upload')
      path = os.path.join(os.path.dirname(__file__), "temploader.tmpl")
      self.response.out.write(template.render(path, template_values))
    else:
      senderror(self)
  def head(self):
    self.response.headers['X-Pingback'] = 'http://yoni-zaf.appspot.com/pingback'
    logging.debug ('got HEAD request')


class Notfound(webapp.RequestHandler):
  def get(self):
    senderror(self)


class ClearCache(webapp.RequestHandler):
  def get(self):
    memcache.flush_all()
    self.response.out.write("Memcache wiped OK")


class Pingback(webapp.RequestHandler):
  #code from GABlog https://launchpad.net/gablog
  def post(self):
    logging.info("Pingback request")
    if len(self.request.body) == 0:
      logging.info("Body is empty!")
      return
    data = xmlrpclib.loads(self.request.body)
    if len(data) != 2:
      return
    if data[1] != 'pingback.ping':
      return
    if len(data[0]) != 2:
      return
    remote_uri = data[0][0]
    local_uri = data[0][1]
    pb = Pingbacks.all(keys_only = True).filter("remoteurl =",remote_uri).fetch(1)
    if len(pb) > 0:
      logging.info("Pingback already exists: "+remote_uri)
      return
    logging.info("Pingback valid! local: '" + local_uri + "' remote: '" + remote_uri + "'")
    p = Pingbacks(
                  localurl = local_uri,
                  remoteurl = remote_uri
                 )
    p.put()
    self.response.out.write("Pingback received OK <br>\nlocal: '" + local_uri + "' remote: '" + remote_uri + "'")


def senderror(self):
  self.response.headers['Content-Type'] = 'text/html'

  if os.path.exists("."+self.request.path):
    self.error(403)
    template_values = {
      'title': '403 Forbidden',
      'error' : '403 - Forbidden area: '+self.request.path,
      }
  else:
    self.error(404)
    template_values = {
      'error' : '404 - File not found: '+self.request.path,
      }
  path = os.path.join(os.path.dirname(__file__), '404.html')
  self.response.out.write(template.render(path, template_values))
  


def main():
  application = webapp.WSGIApplication(
                                       [('/feed', Newsfeed),
                                        ('/files/count', Count),
                                        ('/files/.*', Files),
                                        ('/', Notifier),
                                        ('/notifier.html', Notifier),
                                        ('/upload', Upload),
                                        ('/admin/postnews', PostNewsEntry),
                                        ('/.*.html', Html),
                                        ('/pingback', Pingback),
                                        ('/admin/clear-cache', ClearCache),
                                        ('/.*', Notfound),],
                                       debug=False)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
  main()